<?php
/**
 * @link https://www.kancloud.cn/cleverstone/ymb2
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

namespace builder\widget\ajax;

use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;

/**
 * Ajax:手风琴
 * ```php
 * Accordion::widget([
 *      'id' => 'wwwwww', //如果用于页面遍历中,则必须指定不同`id`!
 *      'items' => [
 *          [
 *              'label' => 'Collapsible Group Item #1',
 *              'content' => 'Anim pariatur cliche...',
 *              'contentOptions' => ['class' => 'in']
 *          ]
 *      ],
 * ]);
 * ```
 * @author cleverstone
 * @since ym2.0
 */
class Accordion extends \yii\bootstrap4\Accordion
{
    public static $autoIdPrefix = 'B4-Accordion';

    /**
     * Initializes the object.
     * This method is called at the end of the constructor.
     * The default implementation will trigger an [[EVENT_INIT]] event.
     */
    function init()
    {
        parent::init();

        $this->options['ym2-bootstrap-plugin'] = 'collapse';
        $this->options['plugin-config'] = '';
    }

    /**
     * {@inheritdoc}
     * @throws InvalidConfigException
     */
    public function run()
    {
        Html::addCssClass($this->options, ['widget' => 'accordion']);
        return implode("\n", [
                Html::beginTag('div', $this->options),
                $this->renderItems(),
                Html::endTag('div')
            ]) . "\n";
    }

    /**
     * Renders a single collapsible item group
     * @param string $header a label of the item group [[items]]
     * @param array $item a single item from [[items]]
     * @param int $index the item index as each item group content must have an id
     * @return string the rendering result
     * @throws InvalidConfigException
     * @throws \Throwable
     */
    public function renderItem($header, $item, $index)
    {
        if (array_key_exists('content', $item)) {
            $id = $this->options['id'] . '-collapse' . $index;
            $expand = ArrayHelper::remove($item, 'expand', false);
            $options = ArrayHelper::getValue($item, 'contentOptions', []);
            $options['id'] = $id;
            Html::addCssClass($options, ['widget' => 'collapse']);

            // check if accordion expanded, if true add show class
            if ($expand) {
                Html::addCssClass($options, ['visibility' => 'show']);
            }

            if (!isset($options['aria-label'], $options['aria-labelledby'])) {
                $options['aria-labelledby'] = $options['id'] . '-heading';
            }

            $encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels;
            if ($encodeLabel) {
                $header = Html::encode($header);
            }

            $itemToggleOptions = array_merge([
                'tag' => 'button',
                'type' => 'button',
                'data-toggle' => 'collapse',
                'data-target' => '#' . $options['id'],
                'aria-expanded' => $expand ? 'true' : 'false',
                'aria-controls' => $options['id']
            ], $this->itemToggleOptions);

            $itemToggleTag = ArrayHelper::remove($itemToggleOptions, 'tag', 'button');
            if ($itemToggleTag === 'a') {
                ArrayHelper::remove($itemToggleOptions, 'data-target');
                $headerToggle = Html::a($header, '#' . $id, $itemToggleOptions) . "\n";
            } else {
                Html::addCssClass($itemToggleOptions, ['feature' => 'btn-link']);
                $headerToggle = Button::widget([
                        'label' => $header,
                        'encodeLabel' => false,
                        'options' => $itemToggleOptions
                    ]) . "\n";
            }

            $header = Html::tag('h5', $headerToggle, ['class' => 'mb-0']);

            if (is_string($item['content']) || is_numeric($item['content']) || is_object($item['content'])) {
                $content = Html::tag('div', $item['content'], ['class' => 'card-body']) . "\n";
            } elseif (is_array($item['content'])) {
                $content = Html::ul($item['content'], [
                        'class' => 'list-group',
                        'itemOptions' => [
                            'class' => 'list-group-item'
                        ],
                        'encode' => false,
                    ]) . "\n";
            } else {
                throw new InvalidConfigException('The "content" option should be a string, array or object.');
            }
        } else {
            throw new InvalidConfigException('The "content" option is required.');
        }
        $group = [];

        if ($this->autoCloseItems) {
            $options['data-parent'] = '#' . $this->options['id'];
        }

        $group[] = Html::tag('div', $header, ['class' => 'card-header', 'id' => $options['id'] . '-heading']);
        $group[] = Html::beginTag('div', $options);
        $group[] = $content;
        if (isset($item['footer'])) {
            $group[] = Html::tag('div', $item['footer'], ['class' => 'card-footer']);
        }
        $group[] = Html::endTag('div');

        return implode("\n", $group);
    }
}